/*
 * COMP6471 Project
 *  
 * This file is created by Yuan Tao (ewan.msn@gmail.com)
 * Licensed under GNU GPL v3
 * 
 * $Author: ewan.msn@gmail.com $
 * $Date: 2011-12-03 21:16:31 +0000 (Sat, 03 Dec 2011) $
 * $Rev: 68 $
 * $HeadURL: http://comp6471.googlecode.com/svn/Project6/src/kklib/UIControllerFacade.java $
 * 
 */

package kklib;

import java.util.ArrayList;
import java.util.Observable;
import java.util.StringTokenizer;

import utils.SysLogger;



// handle all UI request. Singleton Instance & Observable.
public class UIControllerFacade extends Observable {
	private static UIControllerFacade instance;		// Singleton instance.
	
	private Layout layout = null;
	
	public static synchronized UIControllerFacade getInstance() {
		if (instance == null) {
			instance = new UIControllerFacade();
		}
		return instance;
	}
	
	// the user select a game
	public int chooseAGame(ArrayList<Layout> layouts, int gameNo) {
		if (gameNo < 0 || gameNo >= layouts.size()) {
			return -1;
		}
		layout = layouts.get(gameNo - 1);
		notifyAllObservers();
		
		return 0;
	}
	
	// set value/ possible value to cells.
	private int setValues(String values, int type) {
		StringTokenizer st = new StringTokenizer(values); 
		int cnt = st.countTokens();
		if (cnt < 1) {
			return 2;		// empty line
		}
		
		while (cnt-- > 0) {
			String token = st.nextToken();
			
			// check correction of  input value
			if (token.length() != 4) {				
				return 2;		// input error. Game size must be < 10
			}
			
			char ch = token.charAt(0);
			
			if (ch < 'A' || ch > 'A' + layout.gameSize - 1) {
				return 2;		// input error
			}
			ch = token.charAt(1);
			if (ch < '1' || ch > '1' + layout.gameSize - 1) {
				return 2;		// input error
			}
			
			int val = 0;
			
			try {
				val = Integer.parseInt(token.substring(3));
			} catch (NumberFormatException e) {
				return 2;
			}			
			
			// set the value to cell
			if (layout.setCellValue(token.substring(0, 2), val, type) != 0) {
				SysLogger.err("setCellValue. " + type);
				return 3;
			}
		}		
		return 0;
	}
	
	// the user set the value for one or more cells
	public int setValuesForCells(String values) {
		int ret = setValues(values, 1);
		
		notifyAllObservers();
		if (ret != 0) {
			return ret;
		}
		return layout.checkSolution();
	}

	// the user set the possible value for one or more cells
	public int setPossibleValuesForCells(String values) {
		int ret = setValues(values, 0);
		
		notifyAllObservers();
		return ret;
	}
	
	// refresh the UI
	public void notifyAllObservers() {
		setChanged();
		notifyObservers(layout);
	}
	
	// Get hint
	public int getHint(String values) {
		StringTokenizer st = new StringTokenizer(values); 
		int cnt = st.countTokens();
		if (cnt < 1) {
			return 2;		// empty line
		}
		
		while (cnt-- > 0) {
			String token = st.nextToken();
			
			// check correction of  input value
			if (token.length() != 2) {				
				return 2;		// input error.
			}
			
			char ch = token.charAt(0);
			int index = -1;
	
			if (ch < 'A' || ch > 'A' + layout.gameSize - 1) {
				return 2;		// input error
			}
			index = (ch - 'A') * layout.gameSize;

			ch = token.charAt(1);
			if (ch < '1' || ch > '1' + layout.gameSize - 1) {
				return 2;		// input error
			}
			index += ch - '1';

			// get hint for the cell
			layout.rows.get(index).ifHint = true;
			if (layout.rows.get(index).value == 0) {
				layout.rows.get(index).value = layout.rows.get(index).rightVal;
			}
		}		
		
		notifyAllObservers();
		return layout.checkSolution();
	}

}
